In [ ]:
import pandas as pd
import numpy as np
import pandas_datareader as web
import datetime
import plotly.express as px

Yahoo Finance¶

Using the Yahoo API and pandas_datareader library to retrieve quotes for financial instruments (stock indices, stocks, etc.)

In [ ]:
# Downloading Quotes from Yahoo
interval = 'mo'
symbol = '^GSPC'#'^IXIC'#'BCS'#'GE'#'^FCHI'#'^GSPC'
time = 'A'

start = datetime.datetime(1988,1,1) #"1988-01-01"
end = datetime.datetime(2022,5,31)   #"2018-03-01"

df = web.get_data_yahoo(symbol, start = start, end = end, interval=interval)
In [ ]:
# df1 = web.DataReader(name='AMZN', data_source='stooq')
# df1
In [ ]:
f = df.copy()

Leverage¶

In [ ]:
# Definition of leverage level: 'leverage'
leverage = 3

MACD¶

In [ ]:
# import plotly.graph_objects as go

# Get the 26-day EMA of the closing price
k = f['Close'].ewm(span=12, adjust=False, min_periods=12).mean()

# Get the 12-day EMA of the closing price
d = f['Close'].ewm(span=26, adjust=False, min_periods=26).mean()

# Subtract the 26-day EMA from the 12-Day EMA to get the MACD
macd = k - d

# Get the 9-Day EMA of the MACD for the Trigger line
macd_s = macd.ewm(span=12, adjust=False, min_periods=12).mean()

# Calculate the difference between the MACD - Trigger for the Convergence/Divergence value
macd_h = macd.ewm(span=5, adjust=False, min_periods=5).mean() - macd_s

# Add all of our new values for the MACD to the dataframe
f['macd'] = f.index.map(macd)

f['macd'] = f['macd'].ewm(span=5, adjust=False, min_periods=5).mean()
f['macd_h'] = f.index.map(macd_h)
f['macd_s'] = f.index.map(macd_s)

f = f.dropna()

Long - Short¶

In [ ]:
# Definition of long and short trades
conditions = [
    (f['macd_h'] >= 0),
    (f['macd_h'] < 0)]
choices = [1, 0]

f['long/short'] = np.select(conditions, choices, default=0)

Cumulative Returns¶

In [ ]:
# Calculating the rate of return on a stock index
f['dc'] = (f['Close']/f['Close'].shift(1))-1

# Calculating the rate of return on long or short trades taking into account the financial leverage
f['profit'] = f['dc'] * f['long/short'].shift(1) * leverage

f = f.dropna()

# Determination of cumulative return from stock index and model
f['cumprofit'] = (1 + f['profit']).cumprod()
f['cumclose'] = f['Close'][f.index[:]]/f['Close'][f.index[0]]

Drow Dawn¶

In [ ]:
window = 252

# Calculate the max drawdown in the past window days for each day in the series.
# Use min_periods=1 if you want to let the first 252 days data have an expanding window
Roll_Max = f['cumprofit'].rolling(window, min_periods=1).max()
f['DD'] = f['cumprofit']/Roll_Max - 1.0

# Next we calculate the minimum (negative) daily drawdown in that window.
# Again, use min_periods=1 if you want to allow the expanding window
Max_Daily_Drawdown = f['DD'].rolling(window, min_periods=1).min()

Plots¶

In [ ]:
# Determining the period for calculating CAGR
f['dat'] = f.index
diff = f['dat'][-1] - f['dat'][0]
timedelta = pd.Timedelta(diff)
n = timedelta.days


print("Leverage: ", leverage)

print("Cumulative returns of Index: ", np.round(f['cumclose'].iloc[-1], 2))
print("Cumulative returns of Model: ", np.round(f['cumprofit'].iloc[-1], 2))

# CAGR
print("CAGR (Index): ", str(np.round(f['cumclose'].iloc[-1]**((365/n))-1, 2)*100) + " %")
print("CAGR (Model): ", str(np.round(f['cumprofit'].iloc[-1]**((365/n))-1, 2)*100) + " %")


fig = px.line(
                f, 
                x=f.index, 
                y='Close',
                title = symbol + ' (' + interval + ')',
                labels={
                            "Close": "Close",
                            "DateId": "Date",
                        },
                
                width=900,
                height=400
                )
fig.update_layout(
    margin=dict(t=50, b=20),
)
fig.update_xaxes(title=None)
fig.show()


#####################################################################################################
# The function changes the existing names in the legend taken from the column name to the new defined names
def custom_legend_name(new_names):
    for i, new_name in enumerate(new_names):
        fig.data[i].name = new_name
#####################################################################################################

fig = px.line(
                f, 
                x=f.index,
                y=['cumclose', 'cumprofit'],
                #title = symbol + ' (' + interval + ')',
                labels={
                            "value": "Capital",
                            "Date": "Data",
                            "variable": "Legend",
                        },
                log_y=True,
                width=900,
                height=400
                )

custom_legend_name(['Index Price','Model'])




fig.update_layout(legend=dict(
    yanchor="top",
    y=0.99,
    xanchor="left",
    x=0.01
))

fig.update_layout(
    margin=dict(t=50, b=20),
)

fig.update_xaxes(title=None)

fig.show()


fig = px.line(
                f, 
                x=f.index,
                y=['macd', 'macd_s'],
                labels={
                            "value": "MACD",
                            "Date": "Data",
                            "variable": "Legend",
                        },
                width=900,
                height=200
                )
custom_legend_name(['MACD','MACD Signal'])

fig.update_layout(
    margin=dict(t=20, b=20),
    showlegend=False
)

fig.update_xaxes(title=None)

fig.show()


fig = px.line(
                f, 
                x=f.index, 
                y='long/short',
                #title = symbol + ' (' + interval + ')',
                labels={
                            "kappa": "Kappa Value",
                            "Date": "Data",
                            "variable": "Legend",
                        },
                width=900,
                height=200
                )
fig.update_xaxes(title=None)

fig.update_layout(
    margin=dict(t=20, b=20)
)

fig.show()

fig = px.line(
                f, 
                x=f.index,
                y=f['DD'],
                labels={
                            "value": "MACD",
                            "Date": "Data",
                            "variable": "Legend",
                        },
                width=900,
                height=200
                )
#custom_legend_name(['MACD','MACD Signal'])

fig.update_layout(
    margin=dict(t=20, b=20),
    showlegend=False
)

fig.update_xaxes(title=None)

fig.show()

f.to_csv('macd.csv')
Leverage:  3
Cumulative returns of Index:  11.26
Cumulative returns of Model:  209.34
CAGR (Index):  8.0 %
CAGR (Model):  19.0 %